package admin

import (
	"errors"
	"ia/apps/admin/dto/oin"
	oinadmin "ia/apps/admin/dto/oin/admin"
	ooutadmin "ia/apps/admin/dto/oout/admin"
	"ia/apps/admin/middleware/jwt"
	serviceadmin "ia/apps/admin/service/admin"
	"ia/common/icasbin"
	modeladmin "ia/common/model/admin"
	"ia/common/support"
	"ia/common/support/global"
	"strings"

	"github.com/go-sql-driver/mysql"
	"github.com/kataras/golog"
	"github.com/kataras/iris/v12"
	"gorm.io/gorm"
)

func NewAdminUserRoute() *adminUserRoute {
	return &adminUserRoute{}
}

type adminUserRoute struct{}

func (r *adminUserRoute) Login(ctx iris.Context, service serviceadmin.AdminUserService) {
	var (
		code       global.Code
		err        error
		in         = new(oinadmin.AdminUserLoginForm)
		mUser      = new(modeladmin.AdminUser)
		ckPassword bool
		token      string
	)
	// TODO 同时登陆一个账号，将已登陆的用户挤下线
	if err = ctx.ReadJSON(&in); err != nil {
		code = global.CodeParamsError
		goto ERR
	}

	if mUser, err = service.GetByUsername(in.Username); err != nil {
		if errors.Is(gorm.ErrRecordNotFound, err) {
			code = global.CodeRecordNotFound
		}
		goto ERR
	}
	if mUser.Enable <= 0 {
		support.Error(ctx, iris.StatusBadRequest, global.CodeUserDisabled)
		return
	}

	ckPassword = support.CheckPassword(mUser.Password, in.Password)
	if !ckPassword {
		code = global.CodePasswordError
		goto ERR
	}

	if token, err = jwt.GenerateToken(mUser); err != nil {
		code = global.CodeFailure
		goto ERR
	}

	support.Ok(ctx, iris.Map{
		"token": token,
	})
	return
ERR:
	golog.Errorf("用户[%s]登录失败。原因:%s,错误:%v", in.Username, code.String(), err)
	support.InternalServerError(ctx, code)
}

func (r *adminUserRoute) GetUserInfo(ctx iris.Context, service serviceadmin.AdminUserService) {
	var (
		code  global.Code
		err   error
		uid   = ctx.Values().GetInt64Default(global.Uid, 0)
		mUser = new(modeladmin.AdminUser)
	)
	if mUser, err = service.GetById(uid); err != nil {
		if errors.Is(gorm.ErrRecordNotFound, err) {
			code = global.CodeRecordNotFound
		}
		goto ERR
	}
	support.Ok(ctx, mUser)
	return
ERR:
	golog.Errorf("操作失败。原因:%s,错误:%v", code.String(), err)
	support.InternalServerError(ctx, code)
}

func (r *adminUserRoute) Logout(ctx iris.Context) {
	// TODO 清除 redis
	ctx.Values().Reset()

	support.Ok_(ctx)
}

func (r *adminUserRoute) ResetPassword(ctx iris.Context, service serviceadmin.AdminUserService) {
	var (
		code global.Code
		err  error
		in   oinadmin.ResetPassword
	)
	if err = ctx.ReadJSON(&in); err != nil {
		code = global.CodeParamsError
		goto ERR
	}

	if err = service.ResetPassword(in); err != nil {
		if errors.Is(gorm.ErrRecordNotFound, err) {
			code = global.CodeRecordNotFound
		}
		if errors.Is(global.PasswordError, err) {
			code = global.CodePasswordError
		}
		goto ERR
	}
	support.OkTip(ctx, nil)
	return
ERR:
	golog.Errorf("原因：%s，错误：%s", code.String(), err)
	support.InternalServerError(ctx, code)
}

// -------------------
func (r *adminUserRoute) Create(ctx iris.Context, service serviceadmin.AdminUserService) {
	var (
		code       global.Code
		err        error
		enPassword string
		in         oinadmin.AdminUserIn
	)
	if err = ctx.ReadJSON(&in); err != nil {
		goto ERR
	}
	if enPassword, err = support.EncryptPassword(in.Password); err != nil {
		goto ERR
	}
	in.Password = enPassword
	if err = service.Create(in); err != nil {
		if sqlErr, ok := err.(*mysql.MySQLError); ok {
			if sqlErr.Number == 1062 {
				if strings.HasSuffix(sqlErr.Message, "username'") {
					code = global.CodeUsernameDuplicate
				}
			}
		}
		goto ERR
	}
	if err = icasbin.GCasbin.LoadPolicy(); err != nil {
		goto ERR
	}
	support.Ok_(ctx)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}

func (r *adminUserRoute) Delete(ctx iris.Context, service serviceadmin.AdminUserService) {
	var (
		code   global.Code
		err    error
		idList = make([]int64, 0)
	)
	if err = ctx.ReadJSON(&idList); err != nil {
		goto ERR
	}
	for _, v := range idList {
		if v == 1 {
			code = global.CodeUserIsRoot
			support.Error_(ctx, iris.StatusBadRequest, code, "不能删除超级用户", nil)
			return
		}
	}

	if err = service.DeleteByIdList(idList); err != nil {
		goto ERR
	}
	support.OkTip(ctx, nil)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}

func (r *adminUserRoute) Edit(ctx iris.Context, service serviceadmin.AdminUserService) {
	var (
		code global.Code
		err  error
		in   oinadmin.AdminUserIn
	)
	if err = ctx.ReadJSON(&in); err != nil {
		goto ERR
	}
	if err = service.Edit(in); err != nil {
		if sqlErr, ok := err.(*mysql.MySQLError); ok {
			if sqlErr.Number == 1062 {
				if strings.HasSuffix(sqlErr.Message, "username'") {
					code = global.CodeUsernameDuplicate
				}
			}
		}
		goto ERR
	}
	if err = icasbin.GCasbin.LoadPolicy(); err != nil {
		goto ERR
	}
	support.OkTip(ctx, nil)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}

func (r *adminUserRoute) Table(ctx iris.Context, service serviceadmin.AdminUserService) {
	var (
		code  global.Code
		err   error
		in    oin.VxeTableIn
		total int64
		rows  = make([]*ooutadmin.AdminUserOut, 0)
	)
	if err = ctx.ReadQuery(&in); err != nil {
		code = global.CodeParamsError
		goto ERR
	}

	if rows, total, err = service.GetTable(in); err != nil {
		goto ERR
	}
	support.VxeTableData(ctx, in.PageSize, in.CurrentPage, total, rows, nil)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}

func (r *adminUserRoute) List(ctx iris.Context) {
	var (
		// code   global.Code
		// err    error
		result = make([]*ooutadmin.AdminUserOut, 0)
	)
	// if err = repository.NewCurd().OmitDefault().List(&result); err != nil {
	// 	goto ERR
	// }
	support.Ok(ctx, result)
	// ERR:
	// 	golog.Errorf("错误：%s", err)
	// 	support.InternalServerError(ctx, code)
}
